package com.bradz.mytv;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Random;

import android.graphics.Point;
import android.text.format.Time;
import android.util.Log;


public class classChannelHolder {
	//The number of the channel in the network holder
	private int channel_number;
	//The name of the channel in the network holder
	private String channel_name;
	//The last episode watched so that we don't repeat ourselves
	private int last_episode;
	//The current episode so that we can keep watching it on the channel
	private int current_episode;
	//Sets the current delay between this channel and the network
	private int channel_offset;
	//Sets the current progress through an episode
	private long episode_offset;
	//This reminds the media player of the length of the episode so that the player doesn't need to be run for the meta
	private long episode_length;
	//These should be a list of paths where the episode is located
	private ArrayList<String> available_episodes = new ArrayList<String>();
	//These should be a list of paths where the episode is located
	private ArrayList<String> available_episode_paths = new ArrayList<String>();
	//This keeps the show the same as long as it's turned on for this channel
	private boolean show_lock = false;
	public classChannelHolder(int channel_number, String channel_name, ArrayList<String> dbList, boolean set_episodes){
		channel_offset = 0;
		this.channel_number = channel_number;
		this.channel_name = channel_name;
		//We are only given folder paths here, so the individual show strings need to be loaded from them
		for (int i = 0; i < dbList.size(); i++) {
			try{
				this.available_episodes.addAll(get_episodes(dbList.get(i)));
				this.available_episode_paths.add(dbList.get(i));
			}catch(Exception e){
				Log.i("classChannelHolder","Something went horribly wrong! Error: "+e);
			}
		}
		Collections.sort(this.available_episode_paths, new AlphaComparatorPath());
		if(set_episodes){
			Random randomGen = new Random(System.nanoTime());
			int random = 0;
			if(this.available_episodes.size() > 0){
				random = randomGen.nextInt(this.available_episodes.size());
			}
			current_episode = random;
		}
	}
	
	public class AlphaComparatorPath implements Comparator<String> 
  	{
  	    @Override
  	    public int compare (String o1, String o2) 
  	    {
  	        int c;
  	        
  	        String path1 = o1.substring(o1.lastIndexOf('/')==-1?0:o1.lastIndexOf("/")+1,o1.length());
  	      	String path2 = o2.substring(o2.lastIndexOf('/')==-1?0:o2.lastIndexOf("/")+1,o2.length());
  	      
  	        c = path1.compareTo(path2);
  	        if (c != 0) return c;

  	        return -1;
  	    }
  	}
	
	public ArrayList<String> get_episodes(String folder_path){
		File folder = new File(folder_path);
		ArrayList<String> working_episodes = new ArrayList<String>();
		if(folder.listFiles() != null){
			File[] listOfFiles = folder.listFiles();
			for (int i = 0; i < listOfFiles.length; i++) {
				if (listOfFiles[i].exists() && listOfFiles[i].isFile() && 
						!listOfFiles[i].toString().contains(".torrent") && !listOfFiles[i].toString().contains(".txt")) {
			   		working_episodes.add(listOfFiles[i].toString());
		   		}
			}
		}
		return working_episodes;
	}
	public int get_count_working_paths(){
		int count = 0;
		for (int i = 0; i < available_episode_paths.size(); i++) {
			File file = new File(available_episode_paths.get(i));
			Log.i("Channel Holder - file path",available_episode_paths.get(i));
			if (file.exists()) {
				Log.i("Channel Holder - file path","path valid");
		   		count++;
	   		}else{
	   			Log.i("Channel Holder - file path","path invalid");
	   		}
		}
		return count;
	}
	public ArrayList<String> get_channel_shows(){
		ArrayList<String> shows = new ArrayList<String>();
    	for(int i =0; i < get_all_paths().size(); i++){
    		String show_path = get_all_paths().get(i);
    		shows.add(show_path.substring(show_path.lastIndexOf('/')==-1?0:show_path.lastIndexOf("/")+1,show_path.length()));
    	}
    	return shows;
	}
	public int get_current_episode(){
		return current_episode;
	}
	public void set_current_episode(int episode){
		current_episode = episode;
	}
	public void set_episode_offset(long offset){
		episode_offset = offset;
	}
	public long get_episode_offset(){
		return episode_offset;
	}
	public void set_offset(int offset){
		channel_offset = offset;
	}
	public int get_offset(){
		return channel_offset;
	}
	public void reset_offset(){
		channel_offset = 0;
	}
	public void set_episode_length(long episode_length) {
		this.episode_length = episode_length;
	}
	public long get_episode_length() {
		return episode_length;
	}
	public void reset_episode_length(){
		this.episode_length = 0;
	}
	public int get_channel_number(){
		return channel_number;
	}
	public String get_channel_name(){
		return channel_name;
	}
	public String get_episode(int episode){
		if(episode < available_episodes.size()){
			last_episode = current_episode;
			current_episode = episode;
			Log.i("ChannelHolder- get_random_episode","Current: " + current_episode + " Size: " + available_episodes.size());
			return this.available_episodes.get(current_episode);
		}else{
			last_episode = current_episode;
			get_random_episode(false);
			return this.available_episodes.get(current_episode);
		}
	}
	public String get_random_episode(boolean channel_scheduling){
		int episode_substring = 0;
		//There needs to be logic here that prevents the same show from playing twice in a row
		//Find the episode path of the current episode. Don't let another episode in from the 
		//same path unless the length of episode path is 1 or 0
		for(int i = 0; i < available_episode_paths.size(); i++){
			if(available_episodes.get(current_episode).toLowerCase().contains(available_episode_paths.get(i).toLowerCase())){
				episode_substring = i;
				break;
			}
		}
		Log.i("ChannelHolder- get_random_episode","Avoiding: " + episode_substring);
		int random_show = pick_random_show(episode_substring);
		Log.i("ChannelHolder- get_random_episode","Picked Show: " + random_show);
		if (show_lock){
			//The last show will be the same as the current show
			random_show = episode_substring;
		}
		current_episode = pick_random_episode(random_show,channel_scheduling);
		Log.i("ChannelHolder- get_random_episode","Picked Episode: " + current_episode);
		reset_episode_length();
		return this.available_episodes.get(current_episode);
	}
	
	//			      network.get_current_channel().set_current_episode(network.get_current_channel().pick_random_episode(itemId,network.get_settings_holder().channel_scheduling));
	
	/*public String pick_specific_show(int show){
		current_episode = pick_random_episode(show, -1);
		reset_episode_length();
		return this.available_episodes.get(pick_random_episode(show, -1));
	}*/
	
	//Not only does this function have to pick a random show different from the first one, the show it picks must also have relevant media
	private int pick_random_show(int episode_substring){
		Random randomGen = new Random();
		int random_show = randomGen.nextInt(this.available_episode_paths.size());
		//Here there needs to be a check for random show, then episode in that show, giving each equal importance. A show
		//cannot also be played twice in a row
		boolean some_episodes = false;
		int count = 0;
		while(!some_episodes && count < 11){
			random_show = randomGen.nextInt(available_episode_paths.size());
			for(int i = 0; i < available_episodes.size(); i++){
				//This is probably bad form if the list gets super big. Shouldn't be a problem for now though
				//Takes all the episodes out of the list that have the specified path string
				if(available_episodes.get(i).toLowerCase().contains(available_episode_paths.get(random_show).toLowerCase()) && random_show != episode_substring){
					some_episodes = true;
					break;
				}
			}
			count++;
		}
		Log.i("ChannelHolder- pick_random_show","Some episodes: " + String.valueOf(some_episodes));
		if (count >= 10){
			//There was an error. We need to pick a random episode here
			return -1;
		}else{
			return random_show;
		}
	}
	
	//The last show needs to be sent through just in case the first show picked was a dud
	public int pick_random_episode(int random_show, boolean channel_scheduling){
		Random randomGen = new Random();
		if (random_show == -1){
			return randomGen.nextInt(available_episodes.size());
		}
		ArrayList<episode_modified> random_show_episodes = new ArrayList<episode_modified>();
		File file;
		for(int i = 0; i < available_episodes.size(); i++){
			//This is probably bad form if the list gets super big. Shouldn't be a problem for now though
			//Takes all the episodes out of the list that have the specified path string
			if(available_episodes.get(i).toLowerCase().contains(available_episode_paths.get(random_show).toLowerCase())){
				if (!channel_scheduling){
					random_show_episodes.add(new episode_modified(i,0));
				}else{
					file = new File(this.available_episodes.get(i));
					random_show_episodes.add(new episode_modified(i,file.lastModified()));
				}
			}
		}
		
		if (!channel_scheduling){
			return random_show_episodes.get(randomGen.nextInt(random_show_episodes.size())).get_episode();
		}else{
			//Get the current time
			Time now = new Time();
			now.setToNow();
			//Order the episodes by date modified
			random_show_episodes = shellSort(random_show_episodes);
			//find the range of modified allowed for each show
			float percent = returnPercent(now.HOUR+4);
			Log.i("ChannelHolder- pick_random_episode","Percentage: " + String.valueOf(percent));
			Log.i("ChannelHolder- pick_random_episode","Show size after: " + String.valueOf(random_show_episodes.size()));
			Log.i("ChannelHolder- pick_random_episode","Left: " + String.valueOf(((float)random_show_episodes.size()*(.75*percent))));
			Log.i("ChannelHolder- pick_random_episode","Right: " + String.valueOf(((float)random_show_episodes.size()*.25)));
			int randomNumber = (int)(((float)random_show_episodes.size()*(.75*percent))+((float)random_show_episodes.size()*.25));
			Log.i("ChannelHolder- selected_episode","Random Number: " + String.valueOf(randomNumber));
			int episode = randomGen.nextInt(randomNumber);
			Log.i("ChannelHolder- selected_episode","Picked Episode: " + String.valueOf(episode));
			return random_show_episodes.get(episode).get_episode();
		}
	}
	public float returnPercent(float hour){
		if(hour > 24){
			hour -= 24;
		}
		if (hour < 12){
			return 1-hour/12;
		}else{
			return ((hour-12)/12);
		}
	}
	public ArrayList<episode_modified> shellSort(ArrayList<episode_modified> data){
	  int lenD = data.size();
	  int inc = lenD/2;
	  while(inc>0){
	    for(int i=inc;i<lenD;i++){
	    	episode_modified tmp = data.get(i);
	    	long j = i;
	    	while(j>=inc && data.get((int)j-inc).last_modified>tmp.last_modified){
	    	  //data.get((int)j) = data.get((int)j-inc);
	    	  data.set((int)j, data.get((int)j-inc));
	    	  j = j-inc;
	    	}
	    	//data[j] = tmp;
	    	data.set((int)j, tmp);
	    }
	    inc = (inc /2);
	  }
	  return data;
	}
	public int channel_size(){
		return this.available_episodes.size();
	}
	public void remove_path(int index){
		print_episode_paths("before");
		ArrayList<String> available_episodes_holder = new ArrayList<String>();
		if (available_episode_paths.size()>index){
			for (int i = 0; i < available_episodes.size(); i++) {
				if(!available_episodes.get(i).toLowerCase().contains(available_episode_paths.get(index).toLowerCase())){
					available_episodes_holder.add(available_episodes.get(i));
				}
			}
			available_episodes = new ArrayList<String>(available_episodes_holder);
			available_episode_paths.remove(index);
		}
		print_episode_paths("after");
	}
	public ArrayList<String> get_all_paths(){
		return available_episode_paths;
	}
	public void print_episode_paths(String message){
		for(String path:available_episode_paths){
			Log.i("classChannelHolder",message +" path: " + path);
		}
	}
	public String get_show_name(){
		String episode_string = get_episode(get_current_episode());
		String show_string = episode_string.substring(0,episode_string.lastIndexOf('/')==-1?0:episode_string.lastIndexOf("/"));
		return show_string.substring(show_string.lastIndexOf('/')==-1?0:show_string.lastIndexOf("/")+1,show_string.length());
	}
	public String get_episode_name(){
		String episode_string = get_episode(get_current_episode());
		return episode_string.substring(episode_string.lastIndexOf('/')==-1?0:episode_string.lastIndexOf("/")+1,episode_string.length()) + '\t';
		
	}
	public class episode_modified{
		private int episode;
		private long last_modified;
		episode_modified(int episode,long last_modified){
			this.episode = episode;
			this.last_modified = last_modified;
		}
		public int get_episode(){
			return episode;
		}
		public long get_last_modified(){
			return last_modified;
		}
	}
	
	public void switch_show_lock(){
		show_lock = !show_lock;
	}
	
	public boolean get_show_lock(){
		return show_lock;
	}
}
